<!-- index.vue -->
<template>
	<view class="device-container">
		<view v-if="deviceListDataShow.length === 0" class="title-sb no-devicesb"> 设备检测中... </view>
		<view v-else class="title-sb no-devicesb"> 检测完毕 请选择设备 </view>
						<view class="ave-ber-item1">
							<view class="title-bt">
								<text class="title-ssmd">实时密度： </text>
							</view>
		<picker mode="selector" :range="deviceNames" :value="selectedIndex" @change="onPickerChange">
			<view class="picker">{{ selectedDeviceName || '选择蓝牙设备 ▽' }}
			</view>
		</picker>
		</view>
		<canvas class="curve-chart" canvas-id="curveChart"></canvas>
			<view class="ave-ber-item">
				<view class="ave-ber-item1">
				<text class="title-bt">可靠度(%): </text>
				<view class="view-input-send">
					<scroll-view class="scroll-view-ber" scroll-y="false" :scroll-into-view="scrollIntoView">
						<view class="view-rev-gap"></view>
						<text class="text-rev" user-select="true" selectable="true">{{Databer}}</text>
					</scroll-view>
				</view>
				</view>
				<view class="ave-ber-item1">
				<text class="title-bt">样本体积(m³): </text>
				<view class="view-input-send">
					<textarea class="input-send" maxlength="-1" show-count="false" @input="inputSendData" />
				</view>
				</view>
				<view class="ave-ber-item1">
				<text class="title-bt">平均密度(kg/m³):</text>
				<view class="view-input-send">
					<scroll-view class="scroll-view-res" scroll-y="false" :scroll-into-view="scrollIntoView">
						<view class="view-rev-gap"></view>
						<text class="text-rev" user-select="true" selectable="true">{{result}}</text>
					</scroll-view>
				</view>
				</view>
		</view>
		<view class="button-group">
			<button class="bt-disconnect1" @click="btSendTap" hover-start-time="0">检测</button>
						<button class="bt-disconnect" @click="sendData" hover-start-time="0">上传数据</button>

			
		</view>
		<view class="button-group">
			<button class="bt-disconnect" @click="disconnectAndBack" hover-start-time="0">断开连接</button>
			<button class="bt-disconnect" @click="historicaldata" hover-start-time="0">查看历史数据</button>
		</view>
		<text class="title-bt1">技术支持：山西传控科技 </text>
	</view>
</template>
<script>
	// #ifdef APP
	import ecUI from '../../utils/ecUI.js';
	import ecBLE from '../../utils/ecBLE/ecBLE.js';
	// #endif
	// #ifdef MP
	const ecUI = require('../../utils/ecUI.js');
	const ecBLE = require('../../utils/ecBLE/ecBLE.js');
	// #endif
	let ctx;
	let isCheckScroll = true;
	let isCheckRevHex = false;
	let isCheckSendHex = false;
	let sendData = '';
	let weightData = []; // 用于存储重量数据
	let crcData = []; // 用于存储 CRC 校验码
	let avg1 = 0;
	let nowtempData = null;
	let deviceListData = [];
	let yg = '';
	function calculateCRC16(data) {
		const polynomial = 0xA001;
		let crc = 0xFFFF;
		for (let i = 0; i < data.length; i++) {
			crc ^= data.charCodeAt(i);
			for (let j = 0; j < 8; j++) {
				if (crc & 0x0001) {
					crc = (crc >> 1) ^ polynomial;
				} else {
					crc >>= 1;
				}
			}
		}
		return crc.toString(16).toUpperCase().padStart(4, '0');
	}
	export default {
		data() {
			return {
				textRevData: '',
				scrollIntoView: 'scroll-view-bottom',
				averageWeight: '', 
				Databer: '', 
				result: '',
				result1:'11',
				a: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], //存放时间轴
				b: [], 
				dataTimer: null, 
				deviceListDataShow: [],
				deviceNames: [],
				selectedIndex: -1,
				selectedDeviceName: '',
				morningData: '', 
				noonData: '', 
				eveningData: '', 
				yg: '',
			};
		},
		onLoad() {
			ctx = this;
			isCheckScroll = true;
			isCheckRevHex = false;
			isCheckSendHex = false;
			sendData = '';
			weightData = [];
			crcData = [];
			avg1 = 0;
			setInterval(() => {
				ctx.deviceListDataShow = JSON.parse(JSON.stringify(deviceListData))
				ctx.deviceNames = ctx.deviceListDataShow.map(item => item.name)
			}, 800)
			ecBLE.onBLEConnectionStateChange(() => {
				ecUI.showModal('提示', '设备断开连接');
			});
			ecBLE.onBLECharacteristicValueChange((str, strHex) => {
				let data =
					ctx.textRevData +
					'[' +
					ctx.dateFormat('hh:mm:ss,S', new Date()) +
					']: ' +
					str +
					'\r\n';
				ctx.textRevData = data;
				ctx.lightColor = 'green';
				if (ctx.dataTimer) {
					clearTimeout(ctx.dataTimer);
				}
				ctx.dataTimer = setTimeout(() => {
					ctx.lightColor = 'gray';
				}, 2000);
				let receivedCRC = str.slice(-4);
				let weightStr = str.slice(0, -4);
				let weight = parseFloat(weightStr);
				weightData.push(weight); 
				let ssresu = weight / nowtempData;
				ssresu = parseFloat(ssresu.toFixed(2));
				ctx.b.push(ssresu); 
				if (ctx.b.length > 20) {
					ctx.b.shift();
				}
				ctx.drawChart();
				if (!isNaN(weight)) {

					let calculatedCRC = calculateCRC16(weightStr);
					if (receivedCRC === calculatedCRC) {
						crcData.push(100);
					} else {
						crcData.push(0);
					}
				}
				if (crcData.length === 10) { //
					let sum = crcData.reduce((acc, val) => acc + val, 0);
					let avg = sum / crcData.length;
					ctx.Databer = ` ${avg.toFixed(0)}%`;
					crcData = [];
				}
				if (weightData.length === 10) {
					let sum = weightData.reduce((acc, val) => acc + val, 0);
					let avg = sum / weightData.length;
					avg1 = avg;
					ctx.averageWeight = ` ${avg.toFixed(2)}`;
					weightData = []; // 清空数组，准备下一轮数据
					crcData = []; // 清空 CRC 数组，准备下一轮数据
				}
				if (isCheckScroll) {
					if (ctx.scrollIntoView === 'scroll-view-bottom') {
						ctx.scrollIntoView = 'scroll-view-bottom2';
					} else {
						ctx.scrollIntoView = 'scroll-view-bottom';
					}
				}
			});
		},
		onShow() {
			setTimeout(() => {
				ctx.openBluetoothAdapter()
			}, 100)
		},
		onUnload() {
			ecBLE.onBLEConnectionStateChange(() => {});
			ecBLE.onBLECharacteristicValueChange(() => {});
			ecBLE.closeBLEConnection();
		},
		methods: {
			onPickerChange(e) {
				const index = e.detail.value
				this.selectedIndex = index
				this.selectedDeviceName = this.deviceNames[index]
				const selectedDevice = this.deviceListDataShow[index]
				if (selectedDevice.rssi < -75) {
					ecUI.showModal(
						'提示',
						'设备信号强度弱，可能无法正常连接。'
					)
				}
				ecUI.showLoading('设备连接中')
				ecBLE.onBLEConnectionStateChange(res => {
					ecUI.hideLoading()
					if (res.ok) {
						ecBLE.stopBluetoothDevicesDiscovery();
						uni.reLaunch({
							url: getCurrentPages()[getCurrentPages().length - 1].route // 获取当前页面的路由
						});
					} else {
						ecUI.showModal(
							'提示',
							'连接失败,errCode=' + res.errCode + ',errMsg=' + res.errMsg
						)
					}
				})
				ecBLE.createBLEConnection(selectedDevice.id)
				// 只取前两位
				ctx.morningData = this.selectedDeviceName.substring(0, 2);
				// ctx.morningData = this.selectedDeviceName;
			},
			// 新增断开连接并返回方法
			disconnectAndBack() {
				ecBLE.closeBLEConnection();
				ecUI.showModal(
					'提示',
					'设备已断开，请选择设备。'
				)
			},
			historicaldata() {
				uni.navigateTo({
					url: '/pages/datam/datam'
				});
			},

sendData() {
    const currentDate = new Date();
    const month = String(currentDate.getMonth() + 1).padStart(2, '0');
    const day = String(currentDate.getDate()).padStart(2, '0');
    const hours = String(currentDate.getHours()).padStart(2, '0');
    const minutes = String(currentDate.getMinutes()).padStart(2, '0');
    const formattedDate = `${month}-${day}-${hours}:${minutes}`;
    console.log(formattedDate);

    if (!this.morningData) {
        uni.showToast({
            title: '设备未连接',
            icon: 'none',
            duration: 4000 // 设置弹窗持续时间为 4 秒
        });
        return;
    }

    if (!this.noonData) {
        uni.showToast({
            title: '密度数据不能为空',
            icon: 'none',
            duration: 4000 // 设置弹窗持续时间为 4 秒
        });
        return;
    }

    // 弹出确认框
    uni.showModal({
        title: '确认上传',
        content: '是否确认数据正确并上传？',
        success: (res) => {
            if (res.confirm) {
                // 用户点击了确认按钮，执行上传操作
                const dailyData = {
                    date: formattedDate,
                    morning: this.morningData, //存放时间
                    noon: this.noonData, //存放密度数据
                    evening: this.eveningData //存放检测员
                };

                let storedData = uni.getStorageSync('dailyData');
                if (!storedData) {
                    storedData = [];
                } else {
                    try {
                        storedData = JSON.parse(storedData);
                    } catch (error) {
                        storedData = [];
                        console.error('解析本地存储数据时出错:', error);
                    }
                }

                storedData.push(dailyData);
                const stringifiedData = JSON.stringify(storedData);
                uni.setStorageSync('dailyData', stringifiedData);
                console.log('本地存储更新成功');

                uni.redirectTo({
                    url: '/pages/datam/datam'
                });
            } else if (res.cancel) {
                // 用户点击了取消按钮，不执行操作
                console.log('用户取消上传');
            }
        }
    });
},


			openBluetoothAdapter() {
				ecBLE.onBluetoothAdapterStateChange(res => {
					if (res.ok) {
						console.log('Bluetooth adapter ok')
						ctx.startBluetoothDevicesDiscovery()
					} else {
						ecUI.showModal(
							'提示',
							`Bluetooth adapter error | ${res.errCode} | ${res.errMsg}`,
							() => {}
						)
					}
				})
				ecBLE.openBluetoothAdapter()
			},
			startBluetoothDevicesDiscovery() {
				console.log('start search')
				ecBLE.onBluetoothDeviceFound(res => {
					for (const item of deviceListData) {
						if (item.id === res.id) {
							item.name = res.name
							item.rssi = res.rssi
							return
						}
					}
					let manufacturer = ''
					if (res.name.length === 11 && res.name.startsWith('@')) {
						manufacturer = 'eciot'
					}
					if (res.name.length === 15 && res.name.startsWith('BT_')) {
						manufacturer = 'eciot'
					}
					if (manufacturer === 'eciot') {
						deviceListData.push({
							id: res.id,
							name: res.name,
							rssi: res.rssi,
							manufacturer
						})
					}
				})
				ecBLE.startBluetoothDevicesDiscovery()
			},
			// ------------------------------------------------------------------------------------------------------------------------------------搜索蓝牙信号,判断并加入连接列表
			checkScroll(e) {
				if (e.detail.value.length) isCheckScroll = true;
				else isCheckScroll = false;
			},
			checkRevHex(e) {
				if (e.detail.value.length) isCheckRevHex = true;
				else isCheckRevHex = false;
			},
			checkSendHex(e) {
				if (e.detail.value.length) isCheckSendHex = true;
				else isCheckSendHex = false;
			},
			inputSendData(e) {
				sendData = e.detail.value;
			},
			inputSendData1: function(event) {
				// 获取输入框中的值
				const inputValue = event.target.value;
				// 将输入值转换为字符串并覆盖 yg 变量的值
				ctx.yg = String(inputValue);
				console.log('当前 yg 变量的值:', this.yg);
				ctx.eveningData = this.yg;
			},
			btClearTap() {
				ctx.textRevData = '';
			},
			btSendTap() {
				let displaySendData;
				let sampleVolume;
				function isNumber(input) {
					return !isNaN(parseFloat(input)) && isFinite(input);
				}
				if (!isNumber(sendData)) {
					ecUI.showModal('提示', '输入数据必须为数字');
					return;
				}
				if (sendData.length === 0) {
					ecUI.showModal('提示', '请输入样本体积数据');
					return;
				}
				let tempSendData = sendData.replace(/\n/g, '\r\n');
				if (tempSendData.length > 244) {
					ecUI.showModal('提示', '最多只能输入244字节');
					return;
				}
				displaySendData = tempSendData;
				nowtempData = parseFloat(tempSendData);
				let resu = avg1 / parseFloat(tempSendData);
				ctx.result = resu;
				ctx.noonData = parseFloat(resu.toFixed(1));
				ecUI.showModal('提示', '检测完毕！');
			},
			dateFormat(fmt, date) {
				var o = {
					'M+': date.getMonth() + 1, // 月份
					'd+': date.getDate(), // 日
					'h+': date.getHours(), // 小时
					'm+': date.getMinutes(), // 分
					's+': date.getSeconds(), // 秒
					'q+': Math.floor((date.getMonth() + 3) / 3), // 季度
					S: date.getMilliseconds(), // 毫秒
				};
				if (/(y+)/.test(fmt))
					fmt = fmt.replace(
						RegExp.$1,
						(date.getFullYear() + '').substr(4 - RegExp.$1.length)
					);
				for (var k in o)
					if (new RegExp('(' + k + ')').test(fmt)) {
						// console.log(RegExp.$1.length)
						// console.log(o[k])
						fmt = fmt.replace(
							RegExp.$1,
							RegExp.$1.length == 1 ?
							(o[k] + '').padStart(3, '0') :
							('00' + o[k]).substr(('' + o[k]).length)
						);
					}
				return fmt;
			},
			drawChart() {
				const ctx = uni.createCanvasContext('curveChart', this);
				const width = uni.getSystemInfoSync().windowWidth * 9 / 10;
				const height = 200;
				const padding = 40;
				const stepX = (width - 2 * padding) / (this.a.length - 1);
				const maxY = Math.max(...this.b);
				const stepY = (height - 2 * padding) / maxY;
 const borderRadius = 10; // 圆角半径

    // 绘制带圆角的背景
    ctx.beginPath();
    ctx.moveTo(padding + borderRadius, padding);
    ctx.lineTo(width - padding - borderRadius, padding);
    ctx.arcTo(width - padding, padding, width - padding, padding + borderRadius, borderRadius);
    ctx.lineTo(width - padding, height - padding - borderRadius);
    ctx.arcTo(width - padding, height - padding, width - padding - borderRadius, height - padding, borderRadius);
    ctx.lineTo(padding + borderRadius, height - padding);
    ctx.arcTo(padding, height - padding, padding, height - padding - borderRadius, borderRadius);
    ctx.lineTo(padding, padding + borderRadius);
    ctx.arcTo(padding, padding, padding + borderRadius, padding, borderRadius);
    ctx.closePath();

    ctx.fillStyle = '#242049'; // 设置背景颜色，这里使用黑色作为示例
    ctx.fill();
				// 绘制 x 轴
				ctx.beginPath();
				ctx.moveTo(padding, height - padding);
				ctx.lineTo(width - padding, height - padding);
				ctx.strokeStyle = '#00fbaa';
				ctx.lineWidth = 1;
				ctx.stroke();
				// 绘制 y 轴
				ctx.beginPath();
				ctx.moveTo(padding, padding);
				ctx.lineTo(padding, height - padding);
				ctx.strokeStyle = '#00fbaa';
				ctx.stroke();
				// 绘制 x 轴刻度
				for (let i = 0; i < this.a.length; i++) {
					const x = padding + i * stepX;
					ctx.beginPath();
					ctx.moveTo(x, height - padding);
					ctx.lineTo(x, height - padding + 5);
					ctx.strokeStyle = '#00fbaa'; // 设置 x 轴刻度颜色为白色
					ctx.stroke();
					// 绘制 x 轴刻度标签
					ctx.fillText(this.a[i], x - 3, height - padding + 15);
					ctx.fillStyle = '#fff'; // 设置 y 轴刻度标签颜色为白色
				}
				// 绘制 y 轴刻度
				const yTickCount = 5;
				for (let i = 0; i <= yTickCount; i++) {
					const y = height - padding - (i * (height - 2 * padding) / yTickCount);
					ctx.beginPath();
					ctx.moveTo(padding, y);
					ctx.lineTo(padding - 5, y);
					ctx.strokeStyle = '#00fbaa'; // 设置 y 轴刻度颜色为白色
					ctx.stroke();
					// 绘制 y 轴刻度标签
					const tickValue = (i * maxY) / yTickCount;
					const yValue = parseFloat(tickValue).toFixed(2); //保留两位小数
					ctx.fillStyle = '#fff'; // 设置 y 轴刻度标签颜色为白色
					ctx.fillText(yValue, padding - 25, y + 5);
				}
				// 在 x 轴尽头标注单位
				ctx.fillStyle = '#fff';
				ctx.fillText('/次', width - padding + 10, height - padding + 15);
				// 在 y 轴尽头标注单位
				ctx.fillText('kg/m³', padding - 40, padding - 10);
				// 绘制曲线
				ctx.beginPath();
				ctx.moveTo(padding, height - padding - this.b[0] * stepY);
				for (let i = 1; i < this.b.length; i++) {
					const x = padding + i * stepX;
					const y = height - padding - this.b[i] * stepY;
					ctx.lineTo(x, y);
				}
				ctx.strokeStyle = '#00fbaa';
				ctx.lineWidth = 2;
				ctx.stroke();
				// 绘制数据点
				for (let i = 0; i < this.b.length; i++) {
					const x = padding + i * stepX;
					const y = height - padding - this.b[i] * stepY;
					ctx.beginPath();
					ctx.arc(x, y, 1, 0, 2 * Math.PI);
					ctx.fillStyle = '#00fbaa';
					ctx.fill();
				}
				// 执行绘制操作
				ctx.draw();
			},
			// ------------------------------------------------------------------------------------------------------------------------------------------实时图表绘制
		},
		//--------------------------------------------------------------------------------------------------------------------------------methods
	};
</script>
<style>
	/* 设置设备容器为 flex 布局，使其子元素可以相对排列 */
	.device-container {
	    width: 100%; /* 确保父元素宽度占满屏幕 */
	    height: 100vh;
	    display: flex;
	    flex-direction: column;
	    padding: 0px;
	    /* 去掉背景图片注释 */
	    /* background-image: url('http://sunmwvk20.hn-bkt.clouddn.com/back6.png'); */
	    background-color: #2e2951; /* 设置纯色背景，这里使用的是浅灰色，你可以按需修改颜色值 */
		gap: 20px;
		}
    /* 为容器添加相对定位，为内部元素定位提供参考 */
   .container {
      padding: 20px;
      position: relative;
      /* 为了演示效果，给容器添加一个背景色 */
      background-color: lightgray; 
    }

   .title-sb {
      font-size: 20px;
      color: #ffffff;
      margin-bottom: 5px;
	   padding-left: 20px; 
      /* 为文字添加相对定位 */
      position: relative; 
      /* 设置文字的 z-index 大于背景条，使其显示在背景条上方 */
      z-index: 0; 
    }

   .no-devicesb {
      position: relative;
      padding-bottom: 20px; /* 为背景条留出空间 */
      width: 100%; /* 确保父元素宽度占满屏幕 */
    }

   .no-devicesb::after {
      content: "";
      position: absolute;
      left: 0;
      top: 0; /* 从顶部开始 */
      width: 100%;
      height: 100%; /* 高度覆盖整个元素 */
      background-color: #1b1638; /* 背景条颜色 */
      /* 设置背景条的 z-index 大于背景且小于文字 */
      z-index: -1; 
      border-bottom-left-radius: 50px; /* 设置左下角的圆角半径，你可以按需调整数值 */
    }
	.picker {
		font-size: 20px;
		color: #ffffff;
		height: 80%;
		width: 100%;
		padding: 1%;
		border: 3px solid #00fbaa;
		border-radius: 50px;
		margin-bottom: 0px;
	}
	.title-ssmd {
		font-size: 25px;
		color: #ffffff;
		margin-bottom:5px;
	}
	.curve-chart {
		margin-left: 5%;
		width: 100%;
		/* 宽度占满容器 */
		height: 100%;
		/* 高度固定为 200px */
		margin-top: 0px;
		/* 与上方元素保持一定间距 */
		 margin-bottom: 0px;
	}
	.scroll-view-ave1 {
		margin-top: 0px;
		display: flex;
		justify-content: space-between;
	}




	/* 标题与滚动选项组 */
	.title-group {
		display: flex;
		align-items: center;
		margin-bottom: 0px;
	}
	.title-rev {
		font-size: 18px;
		color: #ffffff;
		/* 标题颜色 */
	}
	.scroll-view-res,
	.scroll-view-ave,
	.scroll-view-ber {
		height: 40px;
		width: 130px;
	}

	.view-rev-gap {
		height: 5 px;
	}

	.text-rev {
		font-size: 16px;
		word-break: break-all;
		font-family: Monospace;
		color: #ffffff;
		/* 文本颜色 */
	}

	.title-text,
	.title-send {
		font-size: 15px;
		color: #ffffff;
		margin-bottom: 5px;
	}

	.title-choose {
		font-size: 20px;
		color: #ffffff;
		margin-bottom: 0px;
		text-align: center;
		/* 让容器内的文本左右居中 */
	}
	.light {
		width: 20px;
		height: 20px;
		border-radius: 50%;
		margin: 10px;
	}
	.title-bt {
		font-size: 20px;
		color: #ffffff;
		margin-bottom: 5px;
	}
	.title-bt1 {
		font-size: 12px;
		color: #ffffff;
		margin-bottom: 10px;
		margin-left: 200px;
	}
	.ave-ber-item{
		display: flex;
		flex-direction: column;
		gap: 1px;
	}
	.ave-ber-item1{
		display: flex;
		flex-direction: row;
		justify-content: space-between; /* 使子元素两端对齐 */
		 padding: 0 20px;
	}

	
	/* 输入样本体积部分 */
	.input-group {
		display: flex;
		flex-direction: column;
		margin-bottom: 0px;
	}


	.view-input-send {
		/* padding: 10px; */
		height: 59px;
		width: 150px;
		background-color: #242049;
		border-radius: 4px;
	}

	.input-send {
		height: 60px;
		width: 100%;
		background-color: transparent;
		border: none;
		outline: none;
		color: #ffffff;
	}

	/* 按钮组 */
	.button-group {
		display: flex;
		justify-content: space-between;
	}

	.bt-disconnect {
		flex: 1;
		height: 100%;
		font-size: 20px;
		color: white;
		background-color: #242049;
		border: none;
		border-radius: 40px;
		margin: 0 5px;
		border: 2px solid #00fbaa; /* 添加 2px 宽的黑色实线边框 */
	}
	.bt-disconnect1 {
		flex: 1;
		height: 100%;
		font-size: 20px;
		color: #242049;
		background-color: #00fbaa;
		border: none;
		border-radius: 40px;
		margin: 0 5px;
		border: 2px solid #00fbaa; /* 添加 2px 宽的黑色实线边框 */
		 font-weight: bolder; /* 加粗字体 */
	}


</style>